//////////////////////////////////////////////
// File				:	Input.h
//
// Author			:	Nick Faletra (NF)
//
// Date Created		:	12/22/2013
//////////////////////////////////////////////
#ifndef _INPUT_H_
#define _INPUT_H_

#ifndef DIRECTINPUT_VERSION
	#define DIRECTINPUT_VERSION 0x800
#endif
#include <dinput.h>

#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")

#include <vector>
using std::vector;

#include "../Utility/Utility.h"

class CKeyboard;
class CMouse;
class CJoystick;

enum DeviceFlags { DI_KEYBOARD = 1, DI_MOUSE = 2, DI_JOYSTICKS = 4 };
enum MouseButtons { MOUSE_LEFT = 0, MOUSE_RIGHT = 1, MOUSE_MIDDLE = 2, MOUSE_FOUR = 3, MOUSE_FIVE = 4, MOUSE_MAX };

class CInput
{
	IDirectInput8* m_pDI;

	CKeyboard* m_pKeyboard;
	CMouse* m_pMouse;
	vector<CJoystick*> m_vpJoysticks;

	struct tJoystickSetupInfo
	{
		HWND hWnd;
		bool bExclusive;
	};

	bool InitKeyboard(HWND hWnd, bool bExclusive = false);
	bool InitMouse(HWND hWnd, bool bExclusive = false);
	bool InitJoysticks(HWND, bool bExclusive = false);

	bool CheckJoyNum(int nJoyNum) const;
	
	static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidi, void* pVoid);

	static CInput m_Instance;

	CInput();
	CInput(const CInput&);
	CInput& operator=(const CInput&);
	~CInput();

public:
	static CInput* GetInstance();

	bool Initialize(HWND hWnd, HINSTANCE hInstance, unsigned int initDevices, unsigned int exclusiveDevices = 0);
	void Shutdown();

	void ReadDevices();
	void AcquireAll();
	void UnacquireAll();

	bool KeyDown(unsigned char ucDIKey);
	bool KeyPressed(unsigned char ucDIKey);
	bool KeyPressedEx(unsigned char ucDIKey);
	bool KeyUp(unsigned char ucDIKey);
	bool KeyReleased(unsigned char ucDIKey);
	bool KeyReleasedEx(unsigned char ucDIKey);
	char CheckKeys();
	char CheckBufferedKeysEx();
	unsigned char GetDIKCode();
	unsigned char GetBufferedDIKCodeEx();

	bool MouseButtonDown(unsigned char ucButton);
	bool MouseButtonPressed(unsigned char ucButton);
	bool MouseButtonPressedEx(unsigned char ucButton);
	bool MouseButtonUp(unsigned char ucButton);
	bool MouseButtonReleased(unsigned char ucButton);
	bool MouseButtonReleasedEx(unsigned char ucButton);
	int MouseCheckBufferedButtons();
	int MouseCheckBufferedButtonsEx();
	long MouseMovementX() const;
	long MouseMovementY() const;
	long MouseWheelMovement() const;
	int MouseGetNumButtons() const;
	int MouseGetPosX() const;
	int MouseGetPosY() const;
	void MouseSetPosX(const int nPosX);
	void MouseSetPosY(const int nPosY);

	bool JoystickButtonDown(unsigned char ucButton, int nJoyNum = 0);
	bool JoystickButtonPressed(unsigned char ucButton, int nJoyNum = 0);
	bool JoystickButtonPressedEx(unsigned char ucButton, int JnJoyNum = 0);
	bool JoystickButtonUp(unsigned char ucButton, int nJoyNum = 0);
	bool JoystickButtonReleased(unsigned char ucButton, int nJoyNum = 0);
	bool JoystickButtonReleasedEx(unsigned char ucButton, int nJoyNum = 0);
	bool JoystickDPadDown(int nDir, int nJoyNum = 0);
	bool JoystickDPadPressed(int nDir, int nJoyNum = 0);
	bool JoystickDPadUp(int nDir, int nJoyNum = 0);
	bool JoystickDPadReleased(int nDir, int nJoyNum = 0);
	bool JoystickGetLStickDirDown(int nDir, int nJoyNum = 0);
	bool JoystickGetLStickDirPressed(int nDir, int nJoyNum = 0);
	int JoystickGetLStickXAmount(int nJoyNum = 0);
	int JoystickGetLStickYAmount(int nJoyNum = 0);
	float JoystickGetLStickXNormalized(int nJoyNum = 0);
	float JoystickGetLStickYNormalized(int nJoyNum = 0);
	bool JoystickGetRStickDirDown(int nDir, int nJoyNum = 0);
	bool JoystickGetRStickDirPressed(int nDir, int nJoyNum = 0);
	int JoystickGetRStickXAmount(int nJoyNum = 0);
	int JoystickGetRStickYAmount(int nJoyNum = 0);
	float JoystickGetRStickXNormalized(int nJoyNum = 0);
	float JoystickGetRStickYNormalized(int nJoyNum = 0);
	int JoystickGetLTriggerAmount(int nJoyNum = 0);
	int JoystickGetRTriggerAmount(int nJoyNum = 0);
	float JoystickGetLTriggerNormalized(int nJoyNum = 0);
	float JoystickGetRTriggerNormalized(int nJoyNum = 0);
	int JoystickCheckBufferedButtons(int nJoyNum = 0);
	int JoystickCheckBufferedButtonsEx(int nJoyNum = 0);
	int JoystickGetNumButtons(int nJoyNum = 0) const;
	bool JoystickUnplugged(int nJoyNum = 0) const;
	const char* JoystickGetName(int nJoyNum = 0) const;
	void JoystickSwapRStickAxes(const bool bSwapAxes, int nJoyNum = 0);
};

#endif // _INPUT_H_